package com.bosch.in.rtp1.ept.manager.impl;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.bosch.in.rtp1.ept.constant.FinishRecipeConstant;
import com.bosch.in.rtp1.ept.dao.FinishRecipeDao;
import com.bosch.in.rtp1.ept.manager.FinishRecipeManager;
import com.bosch.in.rtp1.ept.model.dto.FshRcpChartValues;
import com.bosch.in.rtp1.ept.model.dto.FshRcpRecord;
import com.bosch.in.rtp1.ept.model.dto.SelectingString;
import com.bosch.in.rtp1.ept.model.technical.Condition4FinishRecipe;
import com.bosch.in.rtp1.ept.model.technical.FinishedRecipeWrapper;
import com.bosch.in.rtp1.ept.util.DaoFactory;
import com.bosch.in.rtp1.ept.util.ehcache.EhcacheFactory;

/**
 * Concrete implementation of FinishRecipeManager which provides service to manipulate 
 * FinshedRecipe data, delegate data source retrieval and transaction management to 
 * DBConnectionManager attribute.  
 * @author LIV1HC
 *
 */
public class FinishRecipeManagerImpl implements FinishRecipeManager{
	
	/**
	 * used to manage connection
	 */
	private DBConnectionManager dbManager;
	
	/**
	 * dao object
	 */
	private FinishRecipeDao finishRecipeDao;
	
	public FinishRecipeManagerImpl() {
	}

	@Override
	public FinishedRecipeWrapper getFinishedRecipesWrapper(
			Condition4FinishRecipe condition4FinishRecipe) throws SQLException {
		try {
			FinishedRecipeWrapper finishedRecipeWrapper = new FinishedRecipeWrapper();
			finishedRecipeWrapper.setLocations(this.getLocations());
			finishedRecipeWrapper.setStages(this.getStages());
			finishedRecipeWrapper.setEqpType(this.getEqpType());
			finishedRecipeWrapper.setChartValues(this.getFshRcpChartValues(condition4FinishRecipe));
			return finishedRecipeWrapper;
		} finally {
			if (dbManager != null) {
				dbManager.close();
			}
		}
	}

	@Override
	public List<FshRcpChartValues> getFactorList(
			Condition4FinishRecipe condition4FinishRecipe) throws SQLException {
		try
		{
			return this.getFshRcpChartValues(condition4FinishRecipe);
		}
		finally
		{
			if (dbManager != null) {
				dbManager.close();
			}
		}
	}

	@Override
	public List<FshRcpRecord> getFinishedRecipes(
			Condition4FinishRecipe condition4FinishRecipe) throws SQLException {
		try
		{
			return this.getFshRcpRecords(condition4FinishRecipe);
		}
		finally
		{
			if (dbManager != null) {
				dbManager.close();
			}
		}
	}
	
	@Override
	public int getTotalFRRecords() throws SQLException {
		try {
			// lazy init connection
			init();
			return finishRecipeDao.getTotalFRRecords();
		} finally {
			if (dbManager != null) {
				dbManager.close();
			}
		}
		
	}
	
	/***********PRIVATE METHOD****************/
	
	/**
	 * lazy initialize connection when we really need to interact with database and in case 
	 * data can't be found in caching system.
	 * @throws SQLException
	 */
	private void init() throws SQLException {
		if (dbManager == null) {
			dbManager = new DBConnectionManager();
			finishRecipeDao = DaoFactory.getInstance().getFinishRecipeDao(dbManager.getConnection());
		}
	}
	
	/**
	 * Try to get the list of location from cache. 
	 * If it is not found, try to get it from database. Then, adding the list to cache 
	 * @return List<SelectingString>
	 * @throws SQLException
	 */
	private List<SelectingString> getLocations() throws SQLException
	{
		// try to load location list from cache
		List<SelectingString> locations = EhcacheFactory.getLocationEhcacheWrapper().get(FinishRecipeConstant.LOCATION_CACHE_KEY);
		if (locations == null)
			{
				// lazy init connection
				init();
				// load location list from database if it is not in cache 
				locations = finishRecipeDao.getAllLocation();
				//put location list into cache
				if (locations.size()>0)
				{
					EhcacheFactory.getLocationEhcacheWrapper().put(FinishRecipeConstant.LOCATION_CACHE_KEY, locations);
				}
			}			
		return locations;
	}
	
	/**
	 * Try to get the list of Stage from cache. 
	 * If it is not found, try to get it from database. Then, adding the list to cache 
	 * @return List<SelectingString>
	 * @throws SQLException
	 */
	private List<SelectingString> getStages() throws SQLException
	{
		// try to load stage list from cache	
		List<SelectingString> stages = EhcacheFactory.getStageEhcacheWrapper().get(FinishRecipeConstant.STAGE_CACHE_KEY);
		if (stages == null)
			{
				// lazy init connection
				init();
				// load stage list from database if it is not in cache
				stages = finishRecipeDao.getAllStage();
				//put stage list into cache
				if (stages.size()>0)
				{
					EhcacheFactory.getStageEhcacheWrapper().put(FinishRecipeConstant.STAGE_CACHE_KEY, stages);
				}
			}			
		return stages;
	}
	
	/**
	 * Try to get the list of EqpType from cache. 
	 * If it is not found, try to get it from database. Then, adding the list to cache 
	 * @return List<SelectingString>
	 * @throws SQLException
	 */
	private List<SelectingString> getEqpType() throws SQLException
	{
		// try to load eqpType list from cache	
		List<SelectingString> eqptypes = EhcacheFactory.getEqpTypeEhcacheWrapper().get(FinishRecipeConstant.EQPTYPE_CACHE_KEY);
		if (eqptypes == null)
			{
				// lazy init connection
				init();
				// load eqptype list from database if it is not in cache  
				eqptypes = finishRecipeDao.getAllEqpType();
				//put eqptype list into cache
				if (eqptypes.size()>0)
				{
					EhcacheFactory.getEqpTypeEhcacheWrapper().put(FinishRecipeConstant.EQPTYPE_CACHE_KEY, eqptypes);
				}
			}
		return eqptypes;
	}
	
	/**
	 * Try to get the list of FshRcpChartValues from cache based on Condition4FinishRecipe
	 * @param condition4FinishRecipe
	 * @return  + List<FshRcpChartValues> if it is found
	 * 			+ NULL or empty list if it is not found
	 */
	private List<FshRcpChartValues> getFshRcpChartValuesFromCache(Condition4FinishRecipe condition4FinishRecipe)
	{
		//try to load FshRcpChartValues from cache
		List<FshRcpChartValues> fshRcpChartValues = EhcacheFactory.getFshRcpFactorEhcacheWrapper().get(condition4FinishRecipe.getParameterValues().toString());
		
		// if this loading used for exporting, try to get cache of all diagrams
		if (fshRcpChartValues == null && condition4FinishRecipe.getPriority()>0 && condition4FinishRecipe.getProdArea()>0)
		{
			condition4FinishRecipe.builParameterValuesList(0,0);
			List<FshRcpChartValues> fshRcpChartValuesCache = EhcacheFactory.getFshRcpFactorEhcacheWrapper().get(condition4FinishRecipe.getParameterValues().toString());
			
			if (fshRcpChartValuesCache != null )
			{
				fshRcpChartValues = new ArrayList<FshRcpChartValues>();
				// if this loading is used for export, remove unused records
				int i=0;
				while (i<fshRcpChartValuesCache.size())
				{
					FshRcpChartValues fValues = fshRcpChartValuesCache.get(i);
					if (
							fValues.getPriority() == condition4FinishRecipe.getPriority()
							&& fValues.getProdArea() == condition4FinishRecipe.getProdArea() 
						)
					{
						fshRcpChartValues.add(fValues);
					}
					++i;
				}
			}
		} 
		return fshRcpChartValues;
	}
	
	/**
	 * Try to get the list of FshRcpChartValues from database based on Condition4FinishRecipe
	 * @param Condition4FinishRecipe
	 * @return List<FshRcpChartValues>
	 * @throws SQLException
	 */
	private List<FshRcpChartValues> getFshRcpChartValuesFromDao(Condition4FinishRecipe condition4FinishRecipe) throws SQLException
	{
		List<FshRcpChartValues> fshRcpChartValues = new ArrayList<FshRcpChartValues>();
		
		// lazy init connection
		init();
	
		// load fshRcpChartValues from database
		if (condition4FinishRecipe.getPriority()>0 && condition4FinishRecipe.getProdArea()>0)
		{
			condition4FinishRecipe.builParameterValuesList();
		}
		
		fshRcpChartValues = finishRecipeDao.getFactorList(condition4FinishRecipe);
		//put fshRcpChartValues list into cache
		if (fshRcpChartValues.size()>0)
		{
			EhcacheFactory.getFshRcpFactorEhcacheWrapper().put(condition4FinishRecipe.getParameterValues().toString(),fshRcpChartValues);
		}
		
		return fshRcpChartValues;
	}
	
	/**
	 * Try to load the list of FshRcpChartValues from cache first. 
	 * If it is not found, try loading from database
	 * @param Condition4FinishRecipe
	 * @return
	 * @throws SQLException
	 */
	private List<FshRcpChartValues> getFshRcpChartValues(Condition4FinishRecipe condition4FinishRecipe) throws SQLException
	{
		//try to get from cache
		List<FshRcpChartValues> fshRcpChartValues = getFshRcpChartValuesFromCache(condition4FinishRecipe);
		
		if (fshRcpChartValues == null || fshRcpChartValues.size() == 0)
			{
				//try to get from Dao
				fshRcpChartValues = getFshRcpChartValuesFromDao(condition4FinishRecipe);
			}
		
		return fshRcpChartValues;
	}
	
	/**
	 * Try to load the list of FshRcpRecord from cache first. 
	 * If it is not found, try loading from database
	 * @param Condition4FinishRecipe
	 * @return
	 * @throws SQLException
	 */
	private List<FshRcpRecord> getFshRcpRecords(Condition4FinishRecipe condition4FinishRecipe) throws SQLException
	{
		// try to load FshRcpRecord list from cache	
		List<FshRcpRecord> fshRcpRecords = EhcacheFactory.getFshRcpRecords().get(condition4FinishRecipe.getParameterValues().toString());
		
		if (fshRcpRecords == null)
			{
				// lazy init connection
				init();
				// load FshRcpRecord list from database if it is not in cache  
				fshRcpRecords = finishRecipeDao.getFinshedRecipes(condition4FinishRecipe);
				//put FshRcpRecord list into cache
				if (fshRcpRecords.size()>0)
				{
					EhcacheFactory.getFshRcpRecords().put(condition4FinishRecipe.getParameterValues().toString(), fshRcpRecords);
				}
			}
		return fshRcpRecords;
	}
}
